/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2019/3/31 11:53
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.task.manager;

import com.hyacinth.task.callback.WorkCallback;
import com.hyacinth.task.worker.Tasker;
import com.hyacinth.task.worker.Worker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 单实例作业管理器
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class WorkerManager<T> {

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkerManager.class);

    private Map<String, Worker<T>> workerMap = new HashMap<>();

    private WorkerManager() {}

    private static class WorkerManagerHolder {
        private static final WorkerManager INSTANCE = new WorkerManager();
    }

    public static WorkerManager getInstance() {
        return WorkerManagerHolder.INSTANCE;
    }

    /**
     * 创建一个worker
     * @param workParams work参数
     * @param callback   work回调
     * @return work id
     */
    public String createWorker(T workParams, WorkCallback<T> callback) {
        Worker<T> worker = new Worker<>(workParams, callback);
        String workId = worker.getWorkId();
        workerMap.put(workId, worker);
        LOGGER.info("createWorker workId= " + workId);
        LOGGER.info("createWork work count= " + workerMap.keySet().size());
        return workId;
    }

    /**
     * 根据workId获取work参数
     * @param workId 作业id
     * @return 作业参数对象
     */
    public T getWorkParamsByWorkId(String workId) {
        Worker<T> worker = workerMap.get(workId);
        return worker == null ? null : worker.getWorkParams();
    }

    /**
     * 将任务加入的执行列表,加入延时执行
     * @param workId  作业id
     * @param task  任务
     * @param delay 延迟时间毫秒，0为不延迟
     */
    public void work(String workId, Tasker<T> task, long delay) {
        if (workerMap.containsKey(workId)) {
            Worker<T> worker = workerMap.get(workId);
            worker.schedule(task, delay);
        }
    }

    /**
     * 将任务加入的执行列表,按指定的日期时间执行
     * @param task 任务
     * @param time 制定时间点
     */
    public void work(String workId, Tasker<T> task, Date time) {
        if (workerMap.containsKey(workId)) {
            Worker<T> worker = workerMap.get(workId);
            worker.schedule(task, time);
        }
    }

    /**
     * 重复执行任务，按固定的任务间隔，但频率可能会有一些延时
     *
     * @param task   任务
     * @param delay  延迟时间毫秒，0为不延迟
     * @param period 重复执行时间间隔，时间间隔单位毫秒
     */
    public void work(String workId, Tasker<T> task, long delay, long period) {
        if (workerMap.containsKey(workId)) {
            Worker<T> worker = workerMap.get(workId);
            worker.schedule(task, delay, period);
        }
    }

    /**
     * 以固定的时间作为起点，重复执行任务，按固定的任务间隔，但频率可能会有一些延时
     *
     * @param task      任务
     * @param firstTime 开始执行任务的时间
     * @param period    重复执行时间间隔，时间间隔单位毫秒
     */
    public void work(String workId, Tasker<T> task, Date firstTime, long period) {
        if (workerMap.containsKey(workId)) {
            Worker<T> worker = workerMap.get(workId);
            worker.schedule(task, firstTime, period);
        }
    }

    /**
     * 重复执行任务，按固定的任务间隔，每次执行任务的频率一致
     * @param task   任务
     * @param delay  延迟时间毫秒，0为不延迟
     * @param period 重复执行时间间隔，时间间隔单位毫秒
     */
    public void workAtFixedRate(String workId, Tasker<T> task, long delay, long period) {
        if (workerMap.containsKey(workId)) {
            Worker<T> worker = workerMap.get(workId);
            worker.scheduleAtFixedRate(task, delay, period);
        }
    }

    /**
     * 以固定的时间作为起点，重复执行任务，按固定的任务间隔，每次执行任务的频率一致
     *
     * @param task      任务
     * @param firstTime 开始执行任务的时间
     * @param period    重复执行时间间隔，时间间隔单位毫秒
     */
    public void workAtFixedRate(String workId, Tasker<T> task, Date firstTime, long period) {
        if (workerMap.containsKey(workId)) {
            Worker<T> worker = workerMap.get(workId);
            worker.scheduleAtFixedRate(task, firstTime, period);
        }
    }

    /**
     * 停止所有的工作
     */
    public boolean stopAllWork() {
        Collection<Worker<T>> workers = workerMap.values();
        //停止所有的工作
        for (Worker<T> worker : workers){
            worker.stopWork();
        }
        workerMap.clear();
        return true;
    }

    /**
     * 停止某一项工作
     * @param workId 工作id
     */
    public boolean stopWorkByWorkId(String workId) {
        if (workerMap.containsKey(workId)) {
            Worker<T> worker = workerMap.get(workId);
            worker.stopWork();
            workerMap.remove(workId);
        }
        return true;
    }
}
